#! /usr/bin/env bash

REDIS_CLI=redis-cli
SET_SLOW_LOG_MAX_LEN="CONFIG SET slowlog-max-len %s"
GET_SLOW_LOG_MAX_LEN="CONFIG GET slowlog-max-len"
SET_SLOW_LOG_TIME="CONFIG SET slowlog-log-slower-than %s"
PORT=
AUTHEN=
function monitor {
	GET_SLOW_LOG="SLOWLOG GET $MAX_LENGTH"
	LAST_ID_FILE="redis_slow_query_${PORT}.id"
	isOK=$(printf "$SET_SLOW_LOG_MAX_LEN" $5 | $1/${REDIS_CLI} -h $2 -p $3 -a "${AUTHEN}")
	isOK=$(echo $isOK | tr '[a-z]' '[A-Z]')
	if [ "OK" != "$isOK"  ];then
		return 3
	fi
	isOK=$(printf "$SET_SLOW_LOG_TIME" $4 | $1/${REDIS_CLI} -h $2 -p $3 -a "${AUTHEN}")
	isOK=$(echo $isOK | tr '[a-z]' '[A-Z]')
	if [ "OK" != "$isOK"  ];then
		return 3
	fi
	
    if [[ -f ./"$LAST_ID_FILE" ]] ; then
    	LAST_READ_ID=$(cat ./${LAST_ID_FILE})
    else
    	LAST_READ_ID=-1
    fi

	if [[ "$LAST_READ_ID" == "" ]];then
		LAST_READ_ID=-1
	fi

    SLOW_LOG=$(echo ${GET_SLOW_LOG} | $1/${REDIS_CLI} -h $2 -p $3 -d "###" -a "${AUTHEN}")
    CURRENT_ID=$(echo "SLOWLOG GET 1" | $1/${REDIS_CLI} -h $2 -p $3 -a "${AUTHEN}" | awk 'BEGIN{FS="\n"; RS=""} {print $1}')
    LOG_LEN=$(echo "SLOWLOG LEN" | $1/${REDIS_CLI} -h $2 -p $3 -a "${AUTHEN}")
    ix=1

    while (( ix < LOG_LEN )) ; do
        jx=$((CURRENT_ID - ix))
	SLOW_LOG=$(echo -e "$SLOW_LOG" | sed "s/\(###${jx}###[[:digit:]]\{1,\}###[[:digit:]]\{1,\}###[[:alpha:]]\{1,\}\)/###\1/g")
	ix=$((ix + 1))
    done

	OUTPUT=$(echo "$SLOW_LOG" | awk 'BEGIN{RS="######";FS="###";MAX_READ_ID=-1;} 

	function assemble_query(str) {
		
		gsub(/\|/, "<<VERTICAL>>",str);
		if(QUERY == "") {
			QUERY = str;
		} else {
			QUERY = QUERY " " str;
		}
	}

	{
		ix = 1;	
		QUERY = "";
		while(ix <= NF) {
			gsub(/[[:blank:]]*/, "", $ix);
			if(ix == 1) {
	
				ID = $1;
				if(ID <= '$LAST_READ_ID') {
					break;
				}
				if(ID > MAX_READ_ID) {
					MAX_READ_ID=ID;
					printf "%s<<MAX_ID>>", MAX_READ_ID;
				}
			} else if(ix == 2) {
				TIMESTAMP = $2;
			} else if(ix == 3) {
				CONSUMED_TIME = $3;
			} else {
				assemble_query($ix);
			}
			++ix;
		}
		if(ix >= NF) {
			printf "%s<<:>>%s<<:>>%s<<###>>", TIMESTAMP, CONSUMED_TIME, QUERY;
		}
	}')
	if [[ "<<:>><<:>><<###>>" != "$OUTPUT" ]] ; then
		MAX_READ_ID=$(echo ${OUTPUT} | awk 'BEGIN{FS="<<MAX_ID>>"} {print $1}')
		if [[ "" != "$MAX_READ_ID" ]] ; then
		echo ${MAX_READ_ID} > ./${LAST_ID_FILE}
		fi
		export OUTPUT=$(echo ${OUTPUT} | awk 'BEGIN{FS="<<MAX_ID>>"} {print $2}')
	else
		OUTPUT=""
	fi
}

function usage {
	printf "\nUsage check_redis_slow_query:\n"
    printf "\t<-f redis-cli可执行程序的路径>\n"
    printf "\t[-H 设置Redis服务器的主机IP地址,默认为127.0.0.1]\n"
    printf "\t[-p 设置连接Redis服务器的端口,默认为6379]\n"
    printf "\t[-t 设置记录Redis慢查询语句的执行时间阈值,默认为10000微秒]\n"
    printf "\t[-c 设置Redis记录慢查询语句的数目,超过此数值将删除最久的记录,默认为128]\n"
	printf "\t[-a 设置Redis认证密码,默认为空]\n"
    printf "\t-h 打印帮助信息\n"
}

while getopts :f:H:p:t:c:a:h arg ; do
	case $arg in
		f) BINFOLDER=$OPTARG;;
		H) HOST=$OPTARG;;
		p) PORT=$OPTARG;;
    t) THRESHOLD=$OPTARG;;
    c) MAX_LENGTH=$OPTARG;;
		a) AUTHEN=$OPTARG;;
		h) usage
		   exit 0;;
		?) printf "无效的参数!\n"
       usage
       exit 3;;
    esac
done

if [[ ${HOST} == "" ]] ; then
	HOST=127.0.0.1
fi

if [[ ${PORT} == "" ]] ; then
	PORT=6379
fi

if [[ ${THRESHOLD} == "" ]] ; then
    THRESHOLD=10000
fi

if [[ ${MAX_LENGTH} == "" ]] ; then
    MAX_LENGTH=128
fi

if [[ ${BINFOLDER} == "" ]] ; then
	printf "${BINFOLDER}路径下不存在可执行的redis-cli程序.\n"
    usage
    exit 3
fi

monitor ${BINFOLDER} ${HOST} ${PORT} ${THRESHOLD} ${MAX_LENGTH}
SLOW_QUERY_RESULT=$?
if [[ ! -z $OUTPUT ]] ; then
    count=$(printf "%s" "$OUTPUT" | awk 'BEGIN{RS="<<###>>"} END{print NR}')
    printf "${count}<<COUNT>>|Redis_Slow_Query<<###>>%s\n" "$OUTPUT"
    exit 1
else
    exit $SLOW_QUERY_RESULT
fi
